import os
from src.mod import Search
from src.core import Enums
from src.db import dbs, dbm
from sqlalchemy import and_
from typing import Annotated
from pydantic import BaseModel
from src.mod import safe_remove
from src.core.variables.constant import *
from src.core.variables.exception import *
from src.core.variables.cache import Cache
from src.core.variables.temp import MIDDLEWARE
from src.core.variables.function import CREATE_ID
from pydantic import Field, AfterValidator, model_validator


# 自定义验证函数
class _Validate:
    @staticmethod
    def on_empty(v: str) -> str:
        if not v.strip():
            if v not in [""]:
                log.ERROR(f"字段值不能为空: {v}")
                raise ValueError(f"字段值不能为空")
        return v
    
    @staticmethod
    def on_file_path(v: str) -> str:
        if not os.path.exists(v):
            log.ERROR(f"文件不存在: {v}")
            raise ValueError(f"文件不存在！")
        if os.path.splitext(v)[1] not in [".jar", ".zip"]:
            log.ERROR(f"文件格式错误: {v}")
            raise ValueError(f"文件格式错误！")
        return v

    @staticmethod
    def port(v: str) -> str:
        if v == "":
            return v
        if not 0 < int(v) <= 65535:
            log.ERROR(f"端口必须在1-65535范围内: {v}")
            raise ValueError(f"端口必须在1-65535范围内")
        for i in LAW.PORT:
            if i == int(v):
                log.ERROR(f"端口为系统级端口，禁止监听，请修改！: {v}")
                raise ValueError(f"端口为系统级端口，禁止监听，请修改！")
        return v

    @staticmethod
    def node(v: str) -> str:
        if v in ["0"]:
            return v
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session

            db_session: scoped_session
            db_result = db_session.query(dbs.sys_default.Node).filter(dbs.sys_default.Node.node_id == v).first()
            if not db_result:
                log.ERROR(f"节点未注册: {v}")
                raise ValueError(f"节点未注册！")
            elif db_result.status not in ["running"]:
                log.ERROR(f"节点状态错误: {v}")
                raise ValueError(f"节点状态错误，请联系管理员!")
            elif db_result.host == 'localhost':
                return '0'
            return v

    @staticmethod
    def alias(v: str) -> str:
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.alias == v)
                .first()
            ):
                log.ERROR(f"别名重复: {v}")
                raise ValueError(f"别名重复！")
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.alias == v)
                .first()
            ):
                log.ERROR(f"别名重复: {v}")
                raise ValueError(f"别名重复！")
        return v

    @staticmethod
    def keepalive(v: str) -> bool:
        if v == "0":
            return False
        elif v == "1":
            return True
        log.ERROR(f"保活方式不支持: {v}")
        raise ValueError(f"保活方式不支持，操作中止！")

    @staticmethod
    def save_path(v: str) -> str:
        if v == "0":
            return v
        if CONF.PATH.STR.TEMP in v:
            v = v.replace(CONF.PATH.STR.TEMP, CONF.PATH.TEMP)
        # else:
        #     log.ERROR(f"路径错误: {v}")
        #     raise ValueError(f"路径错误！")
        if not os.path.exists(v):
            log.ERROR(f"文件不存在: {v}")
            raise ValueError(f"文件不存在！")
        if os.path.splitext(v)[1] not in [".jar", ".zip"]:
            log.ERROR(f"文件格式错误: {v}")
            raise ValueError(f"文件格式错误！")
        return v

    @staticmethod
    def log_path(v: str) -> str:
        if CONF.PATH.STR.LOG in v:
            v = v.replace(CONF.PATH.STR.LOG, CONF.PATH.LOG)
            if not os.path.exists(v):
                log.ERROR(f"日志文件不存在: {v}")
                raise ValueError(f"日志文件不存在！")
            return v
        log.ERROR(f"日志路径格式错误: {v}")
        raise ValueError(f"日志路径格式错误！")

    @staticmethod
    def to_mode(v: str) -> Enums.JarBehavior | Enums.StaticBehavior:
        if v in ["start"]:
            return Enums.JarBehavior.START
        elif v in ["stop"]:
            return Enums.JarBehavior.STOP
        elif v in ["restart"]:
            return Enums.JarBehavior.RESTART
        elif v in ["enable"]:
            return Enums.StaticBehavior.ENABLED
        elif v in ["disable"]:
            return Enums.StaticBehavior.DISABLED
        log.ERROR(f"操作行为不支持: {v}")
        raise ValueError(f"操作行为不支持，操作中止！")

    @staticmethod
    def on_app_id(v: str) -> str:
        with dbm.get("hosting_Java") as db_session:
            from sqlalchemy.orm import scoped_session

            db_session: scoped_session
            n = 0
            if not (
                db_session.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == v)
                .first()
            ):
                n += 1
        with dbm.get("hosting_Static") as db_session:
            if not (
                db_session.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == v)
                .first()
            ):
                n += 1
        if n == 2:
            log.ERROR(f"应用ID {v} 不存在！")
            raise ValueError(f"应用ID {v} 不存在！")
        return v

    @staticmethod
    def target_node(v: str) -> str:
        with dbm.get("sys_default") as db_session:
            from sqlalchemy.orm import scoped_session

            db_session: scoped_session
            if (
                not db_session.query(dbs.sys_default.Node)
                .filter(dbs.sys_default.Node.ip == v)
                .first()
            ):
                log.ERROR(f"节点 {v} 不存在！")
                raise ValueError(f"节点 {v} 不存在！")
            # TODO 2025年7月7日 校验节点状态是否正常
            return v

    @staticmethod
    def on_sse_id(v: str) -> str:
        if Cache.SSE_CACHE.get(v, None):
            return v
        log.ERROR(f"SSE ID {v} 不存在！")
        raise ValueError(f"SSE ID {v} 不存在！")

    @staticmethod
    def on_line(v: int) -> int:
        if type(v) != int:
            log.ERROR(f"区间类型错误: {v}")
            raise ValueError(f"区间类型错误！")
        if v <= 0:
            log.ERROR(f"区间值错误: {v}")
            raise ValueError(f"区间值错误！")
        return v

    # @staticmethod
    # def on_back_id(v: str) -> str:

    #     return v

    @staticmethod
    def on_mode(v: str) -> str:
        if v not in ["tree", "level", "value"]:
            log.ERROR(f"目录模式错误: {v}")
            raise ValueError(f"目录模式错误！")
        return v
        return v


class register_java_schema(BaseModel):
    """注册Java应用"""

    alias: Annotated[str, AfterValidator(_Validate.alias)] = Field(
        ..., min_length=1, description="别名"
    )
    save_path: Annotated[str, AfterValidator(_Validate.save_path)] = Field(
        ..., min_length=1, description="文件临时保存路径"
    )
    node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="所属节点"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )
    inpara: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="JVM传参"
    )
    port: Annotated[str, AfterValidator(_Validate.port)] = Field(
        ..., description="监听端口号"
    )
    keepalive: Annotated[str, AfterValidator(_Validate.keepalive)] = Field(
        ..., min_length=1, max_length=1, pattern=r"^\d+$", description="保活策略"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )


class register_static_schema(BaseModel):
    """注册Web应用"""

    alias: Annotated[str, AfterValidator(_Validate.alias)] = Field(
        ..., min_length=1, description="别名"
    )
    save_path: Annotated[str, AfterValidator(_Validate.save_path)] = Field(
        ..., min_length=1, description="文件临时保存路径"
    )
    node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="所属节点"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )
    nginx_conf: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="Nginx配置文件"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )

    @model_validator(mode="after")
    def V_nginx_conf(cls, values):
        """校验nginx_conf"""
        # 将nginx_conf添加到nginx.conf中进行语法校验
        app_id = CREATE_ID()
        try:
            conf_file_path = f"{MIDDLEWARE.NGINX.conf_d_dir}/{app_id}_check.conf"
            if not os.path.exists(os.path.dirname(conf_file_path)):
                os.makedirs(os.path.dirname(conf_file_path))
            with open(conf_file_path, "w", encoding="utf-8") as f:
                run_path = f"{CONF.PATH.RUN_STATIC}/{app_id}"
                nginx_conf = values.nginx_conf.replace("@运行池", run_path)
                f.write(nginx_conf)
            MIDDLEWARE.NGINX.change_include(conf_file_path, "add")
            check_result = MIDDLEWARE.NGINX.check()
            if check_result:
                if conf_file_path in check_result:
                    check_result = check_result.replace(conf_file_path, "当前配置")
                if MIDDLEWARE.NGINX.conf_path in check_result:
                    check_result = check_result.replace(
                        MIDDLEWARE.NGINX.conf_path, "nginx.conf"
                    )
                if not "test is successful" in check_result:
                    raise MAIN_VALUE_ERROR_FUNC(
                        loc=("nginx_conf",),
                        msg=check_result,
                        value=values,
                        model_name=__class__.__name__,
                    )
        finally:
            MIDDLEWARE.NGINX.change_include(conf_file_path, "remove")
            safe_remove(conf_file_path)


class deploy_java_schema(BaseModel):
    """部署Java应用"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    save_path: Annotated[str, AfterValidator(_Validate.save_path)] = Field(
        ..., min_length=1, description="文件临时保存路径"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )
    node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="所属节点"
    )
    inpara: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="JVM传参"
    )
    port: Annotated[str, AfterValidator(_Validate.port)] = Field(
        ..., description="监听端口号"
    )
    keepalive: Annotated[str, AfterValidator(_Validate.keepalive)] = Field(
        ..., pattern=r"^\d+$", description="保活策略"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )

    # @model_validator(mode="after")
    # def V_port(cls, values):
    #     """校验端口占用情况"""
    #     port = values.port
    #     app_id = values.app_id
    #     # 校验Java
    #     with dbm.get("hosting_Java") as db_session_hosting_Java:
    #         from sqlalchemy.orm import scoped_session
    #         db_session_hosting_Java: scoped_session
    #         # 校验端口是否被占用
    #         db_result = (
    #             db_session_hosting_Java.query(dbs.hosting_Java.App)
    #             .filter(dbs.hosting_Java.App.port == port)
    #             .all()
    #         )
    #         for i in db_result:
    #             if i and i.app_id != app_id:
    #                 raise MAIN_VALUE_ERROR_FUNC(
    #                     loc=("port",),
    #                     msg="端口已被Java服务占用",
    #                     value=values,
    #                     model_name=__class__.__name__,
    #                 )
    #     # 校验Web
    #     with dbm.get("hosting_Static") as db_session_hosting_Static:
    #         from sqlalchemy.orm import scoped_session
    #         db_session_hosting_Static: scoped_session
    #         db_result = (
    #             db_session_hosting_Static.query(dbs.hosting_Static.App)
    #             .filter(dbs.hosting_Static.App.port == port)
    #             .all()
    #         )
    #         for i in db_result:
    #             if i and i.app_id != app_id:
    #                 raise MAIN_VALUE_ERROR_FUNC(
    #                     loc=("port",),
    #                     msg="端口已被前端静态文件占用",
    #                     value=values,
    #                     model_name=__class__.__name__,
    #                 )
    #     return values

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class deploy_static_schema(BaseModel):
    """部署Web应用"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )
    save_path: Annotated[str, AfterValidator(_Validate.save_path)] = Field(
        ..., min_length=1, description="文件临时保存路径"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )
    node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="所属节点"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )
    nginx_conf: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="nginx配置"
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class config_java_schema(BaseModel):
    """配置Java应用"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    alias: Annotated[str, AfterValidator(_Validate.alias)] = Field(
        ..., min_length=1, description="别名"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )
    inpara: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="JVM传参"
    )
    port: Annotated[str, AfterValidator(_Validate.port)] = Field(
        ..., description="监听端口号"
    )
    keepalive: Annotated[str, AfterValidator(_Validate.keepalive)] = Field(
        ..., pattern=r"^\d+$", description="保活策略"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )

    # @model_validator(mode="after")
    # def V_port(cls, values):
    #     """校验端口占用情况"""
    #     port = values.port
    #     app_id = values.app_id
    #     # 校验Java
    #     with dbm.get("hosting_Java") as db_session_hosting_Java:
    #         from sqlalchemy.orm import scoped_session

    #         db_session_hosting_Java: scoped_session
    #         # 校验端口是否被占用
    #         db_result = (
    #             db_session_hosting_Java.query(dbs.hosting_Java.App)
    #             .filter(dbs.hosting_Java.App.port == port)
    #             .all()
    #         )
    #         for i in db_result:
    #             if i and i.app_id != app_id:
    #                 raise MAIN_VALUE_ERROR_FUNC(
    #                     loc=("port",),
    #                     msg="端口已被Java服务占用",
    #                     value=values,
    #                     model_name=__class__.__name__,
    #                 )
    #     return values

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class config_static_schema(BaseModel):
    """配置Web应用"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="appID"
    )
    alias: Annotated[str, AfterValidator(_Validate.alias)] = Field(
        ..., min_length=1, description="别名"
    )
    time_dir: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="时间目录"
    )
    version: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="版本号"
    )
    notes: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="备注信息"
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class remove_app_schema(BaseModel):
    """删除应用"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")


class control_java_schema(BaseModel):
    """服务控制"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    behavior: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.to_mode)
    ] = Field(..., min_length=1, description="操作行为")

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class control_static_schema(BaseModel):
    """服务控制"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    behavior: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.to_mode)
    ] = Field(..., min_length=1, description="操作行为")

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class rollback_java_schema(BaseModel):
    """java服务回滚"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="回滚ID"
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验其中back_id是否对应着app_id"""
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App_backup)
                .filter(
                    and_(
                        dbs.hosting_Java.App_backup.app_id == values.app_id,
                        dbs.hosting_Java.App_backup.back_id == values.back_id,
                    )
                )
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("back_id",),
                    msg="当前记录不存在！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class rollback_static_schema(BaseModel):
    """web服务回滚"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="回滚ID"
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验其中back_id是否对应着app_id"""
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App_backup)
                .filter(
                    and_(
                        dbs.hosting_Static.App_backup.app_id == values.app_id,
                        dbs.hosting_Static.App_backup.back_id == values.back_id,
                    )
                )
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("back_id",),
                    msg="当前记录不存在！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class info_schema(BaseModel):
    """服务详情"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")


class migrate_schema(BaseModel):
    """服务迁移"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="appID"
    )
    node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="源节点"
    )
    target_node: Annotated[str, AfterValidator(_Validate.node)] = Field(
        ..., min_length=1, description="目标节点"
    )
    appointment: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="预约时间"
    )
    oldkeep: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., description="旧配置保留"
    )


class realog_schema(BaseModel):
    """实时日志"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    since: int = Field(..., description="appID")
 
    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App)
                .filter(dbs.hosting_Java.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


# class stop_realog_schema(BaseModel):
#     """停止实时日志"""

#     sse_id: Annotated[
#         str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_sse_id)
#     ] = Field(..., min_length=1, description="appID")


class remove_java_record_schema(BaseModel):
    """删除java记录"""

    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="记录ID"
    )

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验其中back_id是否对应着app_id"""
        with dbm.get("hosting_Java") as db_session_hosting_Java:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Java: scoped_session
            if not (
                db_session_hosting_Java.query(dbs.hosting_Java.App_backup)
                .filter(
                    and_(
                        dbs.hosting_Java.App_backup.back_id == values.back_id,
                    )
                )
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("back_id",),
                    msg="当前记录不存在！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class remove_static_record_schema(BaseModel):
    """删除web记录"""

    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="记录ID"
    )

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验其中back_id是否对应着app_id"""
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App_backup)
                .filter(
                    and_(
                        dbs.hosting_Static.App_backup.back_id == values.back_id,
                    )
                )
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("back_id",),
                    msg="当前记录不存在！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class migrate_schema(BaseModel):
    """迁移"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )
    target_node: Annotated[str, AfterValidator(_Validate.target_node)] = Field(
        ..., min_length=1, description="目标节点"
    )


class histlog_schema(BaseModel):
    """历史日志"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )
    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="历史id"
    )
    line: Annotated[
        int, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_line)
    ] = Field(..., min_length=1, description="行数区间")

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验app_id是否拥有指定back_id"""
        app_id = values.app_id
        back_id = values.back_id
        app = Search.Hosting.app_by_id(app_id)
        if "Java" in app.__class__:
            with dbm.get("hosting_Java") as db_session_hosting_Java:
                from sqlalchemy.orm import scoped_session

                db_session_hosting_Java: scoped_session
                if (
                    not db_session_hosting_Java.query(dbs.hosting_Java.App_backup)
                    .filter(dbs.hosting_Java.App_backup.back_id == back_id)
                    .frist()
                ):
                    raise MAIN_VALUE_ERROR_FUNC(
                        loc=("back_id",),
                        msg="记录不存在！",
                        value=values,
                        model_name=__class__.__name__,
                    )
        else:
            raise MAIN_VALUE_ERROR_FUNC(
                loc=("app_id",),
                msg="应用类型错误！",
                value=values,
                model_name=__class__.__name__,
            )
        return values


class histlog_list_schema(BaseModel):
    """历史日志列表"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values


class histlog_num_schema(BaseModel):
    """历史日志块数量"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )
    back_id: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="历史id"
    )

    @model_validator(mode="after")
    def V_app_id(cls, values):
        """校验stype与app_id是否匹配"""
        app_id = values.app_id
        with dbm.get("hosting_Static") as db_session_hosting_Static:
            from sqlalchemy.orm import scoped_session

            db_session_hosting_Static: scoped_session
            if not (
                db_session_hosting_Static.query(dbs.hosting_Static.App)
                .filter(dbs.hosting_Static.App.app_id == app_id)
                .all()
            ):
                raise MAIN_VALUE_ERROR_FUNC(
                    loc=("app_id",),
                    msg="应用类型错误！",
                    value=values,
                    model_name=__class__.__name__,
                )
            return values

    @model_validator(mode="after")
    def V_back_id(cls, values):
        """校验app_id是否拥有指定back_id"""
        app_id = values.app_id
        back_id = values.back_id
        app = Search.Hosting.app_by_id(app_id)
        if "Java" in app.__class__:
            with dbm.get("hosting_Java") as db_session_hosting_Java:
                from sqlalchemy.orm import scoped_session

                db_session_hosting_Java: scoped_session
                if (
                    not db_session_hosting_Java.query(dbs.hosting_Java.App_backup)
                    .filter(dbs.hosting_Java.App_backup.back_id == back_id)
                    .frist()
                ):
                    raise MAIN_VALUE_ERROR_FUNC(
                        loc=("back_id",),
                        msg="记录不存在！",
                        value=values,
                        model_name=__class__.__name__,
                    )
        else:
            raise MAIN_VALUE_ERROR_FUNC(
                loc=("app_id",),
                msg="应用类型错误！",
                value=values,
                model_name=__class__.__name__,
            )
        return values


class look_file_content_schema(BaseModel):
    """查看文件内容"""

    app_id: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_app_id] = (
        Field(..., min_length=1, description="appID")
    )
    mode: Annotated[str, AfterValidator(_Validate.on_empty), _Validate.on_mode] = Field(
        ..., min_length=1, description="目录模式"
    )
    path: str = Field(..., min_length=0, description="查询路径")


class file_change_schema(BaseModel):
    """文件修改"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")
    value: Annotated[str, AfterValidator(_Validate.on_empty)] = Field(
        ..., min_length=1, description="内容"
    )
    path: str = Field(..., min_length=0, description="查询路径")


class file_download_schema(BaseModel):
    """jar下载"""

    app_id: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_app_id)
    ] = Field(..., min_length=1, description="appID")


class check_choose_file_schema(BaseModel):
    """检查文件是否合法"""
    
    file_path: Annotated[
        str, AfterValidator(_Validate.on_empty), AfterValidator(_Validate.on_file_path)
    ] = Field(..., min_length=1, description="文件路径")